/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

function denorm(x) { return Math.max(Math.min(Math.round(x*255), 255), 0); }

function hashRGB(r, g, b)
{
	if(arguments.length == 1)
		return arguments.callee(r[0], r[1], r[2]);
	
	function padHex(number)
	{
		var result = denorm(number).toString(16);
		return result.length < 2 ? "0"+result : result;
	}
	
	return "#"+padHex(r)+padHex(g)+padHex(b);
}

function rgb(r, g, b)
{
	if(arguments.length == 1)
		return arguments.callee(r[0], r[1], r[2]);
	return "rgb("+denorm(r)+","+denorm(g)+","+denorm(b)+")";
}

function rgba(r, g, b, a)
{
	if(arguments.length == 1)
		return arguments.callee(r[0], r[1], r[2], r[3]);
	return "rgba("+denorm(r)+","+denorm(g)+","+denorm(b)+","+a+")";
}

function hsl(h, s, l, arr)
{
	if(arguments.length == 1)
		return hsl(h[0], h[1], h[2]);
	var c = [0, 0, 0];
	
	var temp2 = l < 0.5 ? l*(1+s) : l+s-l*s;
	var temp1 = 2*l-temp2;
	var hk = h/360;
	hk -= Math.floor(hk); // -4.1 > -5 => -4.1-(-5) => -4.1+5 => 0.9 => splendid
	var temp3 = [hk+1/3, hk, hk-1/3];
	for(var i=0; i<temp3.length; i++)
	{
		if(temp3[i] < 0)
			temp3[i] += 1;
		if(temp3[i] > 1)
			temp3[i] -= 1;

		if(temp3[i] < 1/6)
			c[i] = temp1+((temp2-temp1)*6*temp3[i]);
		else
		if(temp3[i] < 0.5)
			c[i] = temp2;
		else
		if(temp3[i] < 2/3)
			c[i] = temp1+((temp2-temp1)*(2/3-temp3[i])*6);
		else
			c[i] = temp1;
	}
	
	return arr ? c : rgb(c[0], c[1], c[2]);
}

function hsv(h, s, v, arr)
{
	var hk = h/360;
	hk -= Math.floor(hk); // -4.1 => -5 => -4.1-(-5) => -4.1+5 => 0.9 => splendid
	var f = hk*6;
	var hi = Math.floor(hk*6);
	f -= hi;
	var p = v*(1-s);
	var q = v*(1-f*s);
	var t = v*(1-(1-f)*s);
	var c;
	switch(hi)
	{
	case 0: c = [v,t,p]; break;
	case 1: c = [q,v,p]; break;
	case 2: c = [p,v,t]; break;
	case 3: c = [p,q,v]; break;
	case 4: c = [t,p,v]; break;
	case 5: c = [v,p,q]; break;
	}
	return arr ? c : rgb(c[0], c[1], c[2]);
}

function rgb2hsl(r, g, b)
{
	if(arguments.length == 1)
		return rgb2hsl(r[0], r[1], r[2]);
	
	var h, s, l;
	
	var max = Math.max(Math.max(r, g), b);
	var min = Math.min(Math.min(r, g), b);
	l = (max+min)/2;
	if(Math.abs(max-min) < 1.0e-3)
	{
		s = h = 0;
	} else
	{
		if(max == r && g >= b)
			h = 60*(g-b)/(max-min);
		else
		if(max == r && g < b)
			h = 60*(g-b)/(max-min)+360;
		else
		if(max == g)
			h = 60*(b-r)/(max-min)+120;
		else
			h = 60*(r-g)/(max-min)+240;
		
		if(l <= 0.5)
			s = (max-min)/(2*l);
		else
			s = (max-min)/(2-2*l);
	}
	return [h, s, l];
}

function rgb2hsv(r, g, b)
{
	if(arguments.length == 1)
		return rgb2hsv(r[0], r[1], r[2]);
	
	var h, s, v;
	
	var max = Math.max(Math.max(r, g), b);
	var min = Math.min(Math.min(r, g), b);
	v = max;
	if(Math.abs(max-min) < 1.0e-3)
	{
		s = h = 0;
	} else
	{
		if(max == r && g >= b)
			h = 60*(g-b)/(max-min);
		else
		if(max == r && g < b)
			h = 60*(g-b)/(max-min)+360;
		else
		if(max == g)
			h = 60*(b-r)/(max-min)+120;
		else
			h = 60*(r-g)/(max-min)+240;
		
		if(v > 0)
			s = 1-min/max;
		else
			s = 0;
	}
	return [h, s, v];
}
